package org.xml.sax.helpers;

import java.io.IOException;

import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.DTDHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;


/**
 * 由于ContentHandler接口直接实现不方便，google就为我们封装了这个类，
 * 我们只需要继承这个类然后重写该方法就好了。
 * <p>
 * 这个类可以作为SAX2应用程序的便利基类：它实现了四个核心SAX2接口
 * 1.{@link org.xml.sax.EntityResolver EntityResolver}:定义解析实体的基本接口
 * 2.{@link org.xml.sax.DTDHandler DTDHandler}：接收基本DTD相关事件的通知的接口。
 * 3.{@link org.xml.sax.ContentHandler ContentHandler}： SAX解析方法回调的所有方法的总接口：
 * 4.{@link org.xml.sax.ErrorHandler ErrorHandler}:SAX错误处理程序的基本接口
 * <p>
 * 该方法取代过时的方法：{@link org.xml.sax.HandlerBase HandlerBase}
 *
 * @version 2.0.1 (sax2r2)
 * @see org.xml.sax.EntityResolver
 * @see org.xml.sax.DTDHandler
 * @see org.xml.sax.ContentHandler
 * @see org.xml.sax.ErrorHandler
 */
public class DefaultHandler implements EntityResolver, DTDHandler,
        ContentHandler, ErrorHandler {


    ////////////////////////////////////////////////////////////////////
    // 实体解析器接口(EntityResolver)的默认实现。
    ////////////////////////////////////////////////////////////////////

    /**
     * 默认总是返回null，以便解析器将使用XML文档中提供的系统标识符。
     *
     * @param publicId 公共标识符，如果没有可用的，则返回null。
     * @param systemId XML文档中提供的系统标识符。
     * @return 新的输入源，或null来要求默认行为
     * @throws java.io.IOException      If there is an error setting up the new input source.
     * @throws org.xml.sax.SAXException Any SAX exception, possibly wrapping another exception.
     * @see org.xml.sax.EntityResolver#resolveEntity
     */
    public InputSource resolveEntity(String publicId, String systemId) throws IOException, SAXException {
        return null;
    }


    ////////////////////////////////////////////////////////////////////
    // DTDHandler接口的默认实现
    ////////////////////////////////////////////////////////////////////


    /**
     * 默认情况下，什么也不做。 如果应用程序编写者希望跟踪文档中声明的符号，则可以在子类中重写此方法。
     *
     * @param name     符号名称
     * @param publicId 符号公共标识符，如果不可用，则返回null
     * @param systemId 符号系统标识符。
     * @throws org.xml.sax.SAXException Any SAX exception, possibly wrapping another exception.
     * @see org.xml.sax.DTDHandler#notationDecl
     */
    public void notationDecl(String name, String publicId, String systemId)
            throws SAXException {
        // 老子啥也没做
    }

    /**
     * 默认情况下，什么也不做。应用程序编写者可以在子类中重写此方法，以跟踪文档中声明的未解析的实体。
     *
     * @param name         实体名称。
     * @param publicId     实体公共标识符，如果不可用，则返回null
     * @param systemId     实体系统标识符。
     * @param notationName 关联符号的名称
     * @throws org.xml.sax.SAXException Any SAX exception, possibly  wrapping another exception.
     * @see org.xml.sax.DTDHandler#unparsedEntityDecl
     */
    public void unparsedEntityDecl(String name, String publicId,
                                   String systemId, String notationName)
            throws SAXException {
        // 老子啥也没做
    }


    ////////////////////////////////////////////////////////////////////
    // ContentHandler接口的默认实现。
    ////////////////////////////////////////////////////////////////////


    /**
     * 默认情况下，什么也不做。 如果应用程序编写者希望存储定位器以用于其他文档事件，
     * 那么应用程序编写者可以在子类中重写此方法。
     * @param locator 所有SAX文档事件的定位器。
     * @see org.xml.sax.ContentHandler#setDocumentLocator
     * @see org.xml.sax.Locator
     */
    public void setDocumentLocator(Locator locator) {
        // 老子啥也没做
    }


    /**
     * 接收文件开始的通知。
     * 默认情况下，什么也不做。 应用程序编写者可以在子类中重写此方法，
     * 以便在文档的开始处执行特定的操作（例如分配树的根节点或创建输出文件）
     *
     * @throws org.xml.sax.SAXException Any SAX exception, possibly wrapping another exception.
     * @see org.xml.sax.ContentHandler#startDocument
     */
    public void startDocument()
            throws SAXException {
        // 老子啥也没做
    }


    /**
     * 接收文档结束的通知.
     * 默认情况下，什么也不做。 应用程序编写者可以在子类中重写此方法，
     * 以便在文档的末尾执行特定的操作（例如，完成树或关闭输出文件）。
     * @throws org.xml.sax.SAXException Any SAX exception, possibly wrapping another exception.
     * @see org.xml.sax.ContentHandler#endDocument
     */
    public void endDocument()
            throws SAXException {
        // no op
    }


    /**
     * 接收名称空间映射开始的通知。
     *默认情况下，什么也不做。 应用程序编写者可以在子类中重写此方法，
     * 以在每个名称空间前缀作用域的开始处执行特定的操作（例如存储前缀映射）。
     *
     * @param prefix 正在声明的名称空间前缀。
     * @param uri    名称空间URI映射到前缀。
     * @throws org.xml.sax.SAXException Any SAX exception, possibly  wrapping another exception.
     * @see org.xml.sax.ContentHandler#startPrefixMapping
     */
    public void startPrefixMapping(String prefix, String uri)
            throws SAXException {
        // no op
    }


    /**
     * 接收名称空间映射结束的通知。
     *
     * 默认情况下，什么也不做。 应用程序编写者可以在子类中重写此方法，以便在每个前缀映射的末尾执行特定的操作。
     *
     * @param prefix 正在声明的名称空间前缀。
     * @throws org.xml.sax.SAXException Any SAX exception, possibly  wrapping another exception.
     * @see org.xml.sax.ContentHandler#endPrefixMapping
     */
    public void endPrefixMapping(String prefix)
            throws SAXException {
        // no op
    }


    /**
     * 接收元素开始的通知。
     *
     * 默认情况下，什么也不做。 应用程序编写者可以在子类中重写此方法，
     * 以便在每个元素的开始处执行特定的操作（例如分配新的树节点或将输出写入文件）。
     *
     * @param uri  名称空间URI，如果元素没有名称空间URI，或者名称空间处理没有执行，则为空字符串。
     * @param localName 本地名称（不带前缀），或空字符串，如果命名空间处理没有被执行。
     * @param qName 限定名称（带前缀），或空字符串（如果限定名称不可用）。
     * @param attributes 元素附加的属性。 如果没有属性，它应该是一个空的属性对象。
     * @throws org.xml.sax.SAXException Any SAX exception, possibly wrapping another exception.
     * @see org.xml.sax.ContentHandler#startElement
     */
    public void startElement(String uri, String localName,
                             String qName, Attributes attributes)
            throws SAXException {
        // no op
    }


    /**
     * 接收元素结束的通知。
     *
     * 默认情况下，什么也不做。 应用程序编写者可以在子类中重写此方法，以便在每个元素的末尾执行特定操作（例如，完成树节点或将输出写入文件）。
     * @param uri  名称空间URI，如果元素没有名称空间URI，或者名称空间处理没有执行，则为空字符串。
     * @param localName 本地名称（不带前缀），或空字符串，如果命名空间处理没有被执行
     * @param qName   限定名称（带前缀），或空字符串（如果限定名称不可用）。
     * @throws org.xml.sax.SAXException Any SAX exception, possibly
     *                                  wrapping another exception.
     * @see org.xml.sax.ContentHandler#endElement
     */
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        // no op
    }


    /**
     * 接收元素内部字符数据的通知。
     * 默认情况下，什么也不做。 应用程序编写者可以重写此方法，
     * 以对每个字符数据块执行特定的操作（例如将数据添加到节点或缓冲区，或将其打印到文件中）。
     *
     * @param ch     The characters.
     * @param start  字符数组中的起始位置。
     * @param length 字符数组中要使用的字符数。
     * @throws org.xml.sax.SAXException Any SAX exception, possibly wrapping another exception.
     * @see org.xml.sax.ContentHandler#characters
     */
    public void characters(char ch[], int start, int length)
            throws SAXException {
        // no op
    }


    /**
     * 接收元素内容中可忽略空白的通知。
     * ：默认情况下，什么也不做。 应用程序编写者可以重写此方法，
     * 以针对每个可忽略的空白块（例如将数据添加到节点或缓冲区，或将其打印到文件）采取特定的操作。
     * @param ch     空白字符。
     * @param start  字符数组中的起始位置。
     * @param length 字符数组中要使用的字符数。
     * @throws org.xml.sax.SAXException Any SAX exception, possibly wrapping another exception.
     * @see org.xml.sax.ContentHandler#ignorableWhitespace
     */
    public void ignorableWhitespace(char ch[], int start, int length)
            throws SAXException {
        // no op
    }


    /**
     * 接收处理指令的通知。
     *
     * 默认情况下，什么也不做。 应用程序编写者可以在子类中重写此方法，
     * 以针对每个处理指令采取特定的操作，例如设置状态变量或调用其他方法。
     *
     * @param target 处理指令的目标。
     * @param data   处理指令数据，如果没有提供，则返回null。
     * @throws org.xml.sax.SAXException Any SAX exception, possibly  wrapping another exception.
     * @see org.xml.sax.ContentHandler#processingInstruction
     */
    public void processingInstruction(String target, String data)
            throws SAXException {
        // no op
    }


    /**
     * 接收跳过的实体的通知
     * 默认情况下，什么也不做。 应用程序编写者可以在子类中重写此方法，
     * 以针对每个处理指令采取特定的操作，例如设置状态变量或调用其他方法。
     *
     *
     * @param name 被跳过的实体的名称
     * @throws org.xml.sax.SAXException Any SAX exception, possibly  wrapping another exception.
     * @see org.xml.sax.ContentHandler#processingInstruction
     */
    public void skippedEntity(String name)
            throws SAXException {
        // no op
    }


    ////////////////////////////////////////////////////////////////////
    // 错误处理程序接口(ErrorHandler)的默认实现
    ////////////////////////////////////////////////////////////////////


    /**
     * 接收解析器警告的通知。
     * 默认实现什么都不做。 应用程序编写者可以在子类中重写此方法，
     * 以针对每个警告采取特定的操作，例如将消息插入日志文件或将其打印到控制台。
     * @param e 警告信息编码为例外。
     * @throws org.xml.sax.SAXException Any SAX exception, possibly wrapping another exception.
     * @see org.xml.sax.ErrorHandler#warning
     * @see org.xml.sax.SAXParseException
     */
    public void warning(SAXParseException e)
            throws SAXException {
        // no op
    }


    /**
     * 接收可恢复解析器错误的通知。
     *
     * 默认实现什么都不做。 应用程序编写者可以在子类中重写此方法，
     * 以针对每个错误采取特定的操作，例如将消息插入日志文件或将其打印到控制台。
     * @param e The warning information encoded as an exception.
     * @throws org.xml.sax.SAXException Any SAX exception, possibly wrapping another exception.
     * @see org.xml.sax.ErrorHandler#warning
     * @see org.xml.sax.SAXParseException
     */
    public void error(SAXParseException e)
            throws SAXException {
        // no op
    }


    /**
     * 报告一个致命的XML解析错误。
     * 默认实现抛出一个SAXParse异常。
     * 如果应用程序编写者需要针对每个致命错误采取特定的操作（例如将所有错误收集到单个报告中），
     * 那么应用程序编写者可以在子类中重写此方法：在任何情况下，应用程序必须在调用此方法时停止所有常规处理 ，
     * 因为文档不再可靠，解析器可能不再报告解析事件。
     * @param e The error information encoded as an exception.
     * @throws org.xml.sax.SAXException Any SAX exception, possibly wrapping another exception.
     * @see org.xml.sax.ErrorHandler#fatalError
     * @see org.xml.sax.SAXParseException
     */
    public void fatalError(SAXParseException e)
            throws SAXException {
        throw e;
    }

}
